package com.game.core.dbwrite.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.game.core.dbcs.DBCS;
import com.game.core.dbcs.daoproxy.IDaoExecutor;
import com.game.core.dbwrite.constant.DBOperationType;
import com.game.core.dbwrite.domain.MemoryCache;
import com.game.core.dbwrite.domain.StoreEntity;

public class WriteToDBUtil
{
	public static final Logger logger = LoggerFactory.getLogger(WriteToDBUtil.class);
	private static Map<String, Method> methodMap = new HashMap<String, Method>();
	private static Map<String, Object> daoMap = new HashMap<String, Object>();

	@SuppressWarnings({ "unchecked" })
	public static void writeStoreEntityToDB(StoreEntity entity)
	{
		try
		{
			// TODO 先关闭写数据库时的日志
			// dumpInfo(entity);

			if (entity == null)
			{
				logger.debug("WriteStoreEntityToDB Entity is null.");
				return;
			}

			Class<?> clazz = entity.getClazz();
			DBOperationType type = entity.getOperationType();
			byte[] serilizedClass = entity.getSerilizedClass();
			
			// cuichao 目前可能会出现反序列化失败的情况
			Object bean = null;
			try
			{
				bean = KryoUtil.deSerilize(clazz, serilizedClass);
			}
			catch(Exception e)
			{
				logger.error("WriteStoreEntityToDB: exception arised!!! class is " + clazz + ", buffer is " + Arrays.toString(serilizedClass), e);
				dumpInfo(entity);
				throw e;
			}
			if(bean == null)
			{
				logger.error("WriteStoreEntityToDB: KryoUtil deserilize failed. bean is null.");
				throw new Exception("bean is null");
			}

			String beanPath = clazz.getName();
			// logger.debug("Bean path: " + beanPath);
			String[] splitBeanPath = beanPath.split("\\.");
			if (splitBeanPath == null || splitBeanPath.length < 3)
			{
				logger.debug("Bean path is not correct.");
				return;
			}

			String daoPath = "com.game.dbpersistence." + splitBeanPath[splitBeanPath.length - 3] + ".dao.I" + splitBeanPath[splitBeanPath.length - 1] + "Dao";
			// logger.debug("IDao path: " + daoPath);
			String methodName = "";
			switch (type)
			{
			case INSERT:
				methodName = "insert" + splitBeanPath[splitBeanPath.length - 1];
				break;
			case UPDATE:
				methodName = "update" + splitBeanPath[splitBeanPath.length - 1];
				break;
			case DELETE:
				methodName = "delete" + splitBeanPath[splitBeanPath.length - 1];
				break;
			}
			// logger.debug("Method name: " + methodName);
			if (methodMap.containsKey(methodName) && daoMap.containsKey(daoPath))
			{
				Method m = methodMap.get(methodName);
				Object dao = daoMap.get(daoPath);
				if (m != null && dao != null)
				{
					try
					{
						m.invoke(dao, bean);
						// logger.debug("Execute Map." + methodName);
					}
					catch (IllegalAccessException e)
					{
						logger.debug("Exception.", e);
					}
					catch (IllegalArgumentException e)
					{
						logger.debug("Exception.", e);
					}
					catch (InvocationTargetException e)
					{
						logger.debug("Exception.", e);
					}
				}
				else
				{
					logger.debug(daoPath + "no such Method.");
				}
			}
			else
			{   // 如果方法不在Map中，通过反射获取
				Class<IDaoExecutor> daoClazz = null;
				try
				{
					daoClazz = (Class<IDaoExecutor>) Class.forName(daoPath);
				}
				catch (Exception e)
				{
					// e.printStackTrace();
					logger.error("Exception : ", e);
				}
				if (daoClazz == null)
				{
					logger.debug("Reflect IDao " + daoPath + " failed.");
					return;
				}
				Object dao = DBCS.getExector(daoClazz);
				if (dao == null)
				{
					// logger.debug("DBCS getExecutor Dao is null.");
					return;
				}
				daoMap.put(daoPath, dao);

				try
				{
					Method m = daoClazz.getMethod(methodName, clazz);
					if (m != null)
					{
						methodMap.put(methodName, m);
						m.invoke(dao, bean);
					}
					else
					{
						logger.debug(daoClazz.getName() + "no such Method.");
					}
				}
				catch (Exception e)
				{
					logger.error(daoClazz.getName() + " get Method failed.", e);
				}
			}
		}
		catch (Exception e)
		{
			logger.error("exception. ", e);
		}
	}
	
	public static void dumpInfo(StoreEntity entity)
	{
		logger.debug("==========================================" + entity.getClazz().getName());
		MemoryCache.dumpMap();
	}
}